I found the solution. Hopefully others will benefit from this, as most other posts I've seen on the subject result in double loading of jQuery and the need to carefully manage how and when you load the clientlib which contains the version of jQuery you want.
First though, the OOTB version of jQuery is an updated version of v1.12.4 it already contains fixes for the known vulnerabilities. So if you are looking to update jQuery simply to pass a security scan, then you should read this:
https://docs.mktossl.com/docs/experience-cloud-kcs/kbarticles/KA-21173.html
If you still want to use a newer version of jQuery, then the solutions is really simple.
Create your own clientlib that contains the version of jQuery that you want.
Set the categories property of your clientlib to be "jquery".
Set the replaces property of your clientlib to be "/libs/clientlibs/granite/jquery".
Then add your clientlib to the page as required
<sly data-sly-call="${clientLib.js @ categories='jquery'}"/>
The key point is to set the 'replaces' property, otherwise you'll end up loading both the OOTB code and your own version.