Service-oriented architecture is really about coupling and, as with all architecture, is not too interested in the implementation.
The ideal is to decouple services in order to expose autonomous functionality. How that service is implemented should not matter. You may even expose functionality from a a legacy monolithic application.
Along with the coupling goes what I call reachability. You need to execute some code and there are going to be a couple of ways to do that:
- copy & paste
- call existing function
- reference assembly
- call over-the-wire / out-of-process
In order to have autonomous business components you need to have some deployment strategy. This is where things get more involved as updating a legacy system that exposes services is a lot harder than, say, a bounded context (in domain-driven design parlance) as a micro-service.
Client/Server implementations may look very much like SOA if your server is exposing services in a rather easy-to-access fashion (say a REST API). If you look at things logically from a high enough level they start looking very much alike. In that regard SOA is actually really rather old hat and even though we have "newer" techniques they still truly fall under the SOA banner.