I think I might have just answered my own question. It will specialize to Wrapper{typeof(sin)}, but not if Wrapper <: Function:
julia> struct Wrapper{F<:Function}
f::F
end
julia> struct Wrapper2{F<:Function} <: Function
f::F
end
julia> (w::Wrapper{F})(x) where {F} = w.f(x)
julia> (w::Wrapper2{F})(x) where {F} = w.f(x)
julia> f_func(f, num) = ntuple(f, div(num, 2))
julia> f_func(sin, 5); f_func(Wrapper(sin), 5); f_func(Wrapper2(sin), 5)
(0.8414709848078965, 0.9092974268256817)
julia> Base.specializations(@which f_func(sin, 5))
Base.MethodSpecializations(svec(MethodInstance for f_func(::Wrapper{typeof(sin)}, ::Int64), MethodInstance for f_func(::Function, ::Int64), nothing, nothing, nothing, nothing, nothing))
So we can see there is f_func(::Wrapper{typeof(sin)}, ::Int64). But since Wrapper2 <: Function, it results in no specialisation!