You can dispatch on argument values by moving values into the type domain — that is, you wrap the value in a type. A generic type that is provided for this purpose is Val.
Parameters are always involved in the type domain, even when they’re not types. If you go beyond type-based polymorphism, you start losing the distinction between types and their values.
A rewrite of the original example could look like this:
f(x, n::Number) = f(x, Val(n))
f(x, ::Val{N}) where N = x^N
I really suggest that you don’t use methods like the first method on a regular basis, literal_pow is only used because powers of integer literals can lower to it and leverage constant optimizations. If you use it on a variable whose runtime value can vary without any restrictions, then you’re compiling the second method repeatedly. That can easily ruin any performance benefits.