This is not about the instruction cache. This is about branch prediction. Calling a function pointer (almost?) guarantees that the branch prediction will fail, unlike a switch statement. Not cool in inner loops.
Are you sure? AFAIK the prediction will usually assume that the called address will be the same as the last one, so in an inner loop (eg. mapping a function over an array), only the first call would take a long time, and then only by 20-25 cycles. If a loop is so tight that 5 or so cycles per iteration matters, there shouldn't be a function call in it in the first place.
(I've googled earlier and someone measured a virtual call in a tight loop to take about twice the time of a direct one. Intel doc says a call is about 5 cycles. That would mean an extra 5 cycles or so for the indirection.)
Practically all modern CPUs have indirect branch prediction. The overhead of a function pointer call is practically zero unless the target of the function pointer is actually completely random, which it rarely is: most of the time it's constant for a long period of time (e.g. an in inner loop) until it's changed.