It doesn't matter if your holder is heap or stack allocated, the d pointer is always heap allocated and the only reference to it is the private internal. With interfaces you either have an awful dummy static constructor for your private object somewhere or you have a non-virtual parent class with dummy implementations of all its functions and a mangled constructor that produces its private child.
For the developer, interfaces are cleaner, but for users, the interface style is leaky where PIMPL is not. That makes it superior. It also avoids overriding the intent of inheritance as a way of achieving ABI compatibility when it already has a significant and intentional function of runtime polymorphism, and can easily confuse users as to whether the implementation is to preserve the ABI or provide multiple implementations in the same release.