100% agree. Using 'instance of' in Java is a terrible anti-pattern, same as trying to do pattern matching. You should lift that code into instance methods and let the runtime pick the right implementation.
There are some cases when it's actually simpler or more maintainable or more useful to do the dispatch locally. A language that allows you to both is tougher to learn and can have a higher risk of pitfalls, but also means that a seasoned practitioner can apply the right tool in the right situation.
In terms of the classic 'patterns', it's the difference between standard dispatch and the 'Visitor' pattern. There are cases where you want to specify each case of data structure locally, and others where you want to specify each method of each variant locally. Welcome to the expression problem!
There are cases in Java where you do want a true POJO - just a bag of structured data. This is probably a very strong candidate for using along side that.
The downside to that is if you want to write a new function that deals different subclasses, you can't keep all the logic in one place; you have to spray its implementation across all the different types it has to handle. This is the #1 reason I prefer languages with sum types and pattern matching (or the ability to emulate it via unions and instanceof checks, e.g. TypeScript or Python + mypy).
You could implement a crappy union type in Java with a type-safe API, but if you want to program in that style you are really better off using an ML or Scala.
I actually disagree. instanceof is a fast operation on the JVM and can make code easier to read than equivalent OOP (less hopping around). However, you must be careful that all cases are covered since Java lacks exhaustive pattern matching.